{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "8b57bfa0",
   "metadata": {
    "jp-MarkdownHeadingCollapsed": true
   },
   "source": [
    "# <a id=\"top\"> Replication for [*Optimal Fiscal Policy With Heterogeneous Agents and Capital: Should We Increase or Decrease Public Debt and Capital Taxes?*](https://xavier-ragot.fr/pdf/progress/LeGrand_Ragot_debt.pdf)\n",
    "\n",
    "## Authors: François Le Grand and Xavier Ragot\n",
    "\n",
    "\n",
    "Please feel free to contact any of us if you have problems with these replication files: \n",
    "* LeGrand: Rennes School of Business, <tt>francois.le-grand@rennes-sb.com</tt>.\n",
    "* Ragot: SciencesPo, OFCE, and CNRS, <tt>xavier.ragot@sciencespo.fr</tt>.\n",
    "  \n",
    "\n",
    "## Date: September, 2024\n",
    "\n",
    "Please read the *README.md* file for further explanations.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "020479a5",
   "metadata": {},
   "source": [
    "# Organization and summary of the computational solution  <a id=\"summary-computational-solution\"></a>[<font size=1>(back to top)</font>](#top)\n",
    "\n",
    "The computation of the truncated Ramsey model at the steady state is organized into nine notebooks.\n",
    "\n",
    "1. [**Main.ipynb**](./Main.ipynb) (the current notebook): calls external functions and performs the computation of the Ramsey steady-state solution for a given calibration. This is the only notebook that actually needs to be run. \n",
    "\n",
    "2. [**Structures.ipynb**](./Structures.ipynb): contains the definitions of the main structures used by the computational implementation, as well as some specific constructors. The structures are:\n",
    "* `Economy`: collects the parameters that characterize the economy (utility and related functions, productivity process, grids, $\\ldots$).\n",
    "* `AiyagariSolution`: contains the solution of the individual Aiyagari model (prices, policy functions, $\\ldots$).\n",
    "* `TruncatedModel`: collects the solution of the truncated model, including:\n",
    "    * the allocation, collected in the `TruncatedAllocation` structure;\n",
    "    * the within-heterogeneity parameters, `ξ`s., , collected in the structure `ξs_struct`.\n",
    "* `Ramsey`: collects the main variables of the Ramsey solution, including:\n",
    "    * the weights of  various histories  `Weights` structure;\n",
    "    * the Lagrange multipliers for histories, collected in the structure `LagrangeMult`.\n",
    "\n",
    "3. [**SolveAiyagari.ipynb**](./SolveAiyagari.ipynb): computes the solution of the individual Aiyagari model using the EGM method. The implemented solution takes  prices (interest rate and thus wage rate) as given and returns the level of public spending  that allows the government budget to be balanced. Public debt is also the endogenous result of the clearing of financial markets. The core function of this notebook is **steady** which takes an economy of type `Economy`  as input and returns the solution of the Aiyagari model as type `AiyagariSolution`. The signature of the function is:\n",
    "> `steady(economy::Economy)::AiyagariSolution`\n",
    "\n",
    "4. [**Truncation.ipynb**](./Truncation.ipynb): computes the truncated model from the solution of the Aiyagari model. The core function of this notebook is **TruncatedModel** which takes as input: truncation length parameters, a solution of the Aiyagari model of type `AiyagariSolution`, an economy of type `Economy`. The function returns the truncated model of type `TruncatedModel`. The function can thus be seen as an extended constructor of the type `TruncatedModel`. The function signature is (in the following, `I` is always a subtype of ̀`Int` and `T` is a subtype of `Real`):\n",
    "\n",
    "    > `TruncatedModel(N::I, refiNs::Vector{I}, solution::AiyagariSolution, economy::Economy)::TruncatedModel`\n",
    "\n",
    "    where `N` and `refiNs` are the truncation lengths of the method. It is important to check that the results do not depend too much on the values for these two parameters, but in practice policy functions barely change once truncation lengths are not too small. \n",
    "\n",
    "\n",
    "5. [**Ramsey.ipynb**](./Ramsey.ipynb): computes the Ramsey solution of the truncated model. The core function of the notebook is **ramsey_GHH**, which takes as input: a truncated model of type `TruncatedModel`, the corresponding Aiyagary solution of type `AiyagariSolution`, and the corresponding economy of type `Economy`. The function returns the Ramsey solution of type `Ramsey`. The function signature is:\n",
    "\n",
    "> `ramsey_GHH(truncatedModel::TruncatedModel,solution::AiyagariSolution,economy::Economy)::Ramsey`\n",
    "\n",
    "6. [**Utils.ipynb**](./Utils.ipynb): contains useful functions that are not central to the algorithm (such as computing a Gini index or our linearization implementation). They are collected in the same notebook for the sake of convenience. \n",
    "7.  [**ToDynare.ipynb**](./ToDynare.ipynb) This notebook contains the function that saves the truncated Ramsey allocation on a `mat` file to be used in [Dynare](https://www.dynare.org/). The core function is **Write_Dynare**, which takes as input: a filename of type `String`, a Ramsey solution of type `Ramsey`, the corresponding Aiyagary solution of type `AiyagariSolution`, and the corresponding economy of type `Economy`. It returns nothing but write the file `filename`, which is a `mat` file. The function signature is:\n",
    "\n",
    "> `Write_Dynare(filename::String,ramsey::Ramsey,solution::AiyagariSolution,economy::Economy)::Nothing` \n",
    " \n",
    "8.  [**Reiter.ipynb**](./Reiter.ipynb) This notebook saves the data to simulate the model using the Reiter's technique (without optimal policies). We use the Dynare solver to solve the model.\n",
    "\n",
    "9.  [**R_functions.ipynb**](./R_functions.ipynb) This notebook This notebook gathers the functions that requires calling the [R language](https://www.r-project.org/). This notebook is not essential to the replication and can be skipped. Indeed, it is only injvolved in the computation of the persistence and innovation of the aggregate labor process.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "44278442",
   "metadata": {},
   "source": [
    "# Computing the Ramsey solution at the steady state <a id=\"menu\"></a>[<font size=1>(back to top)</font>](#top)\n",
    "\n",
    "We split the computation into 3 cells:\n",
    "\n",
    "1. [Importing](#packages) external packages;\n",
    "\n",
    "2. [Including](#notebooks) external notebooks;\n",
    "\n",
    "3. [Computing](#comps) the Ramsey solution: this is obviously the core cell.\n",
    "\n",
    "\n",
    "## Importing external packages <a id=\"packages\"></a>[<font size=1>(back to menu)</font>](#menu)\n",
    "\n",
    "We import the external modules we use. In some cases we specify which functions we use. Note that these imports are valid for all notebooks (but should be repeated if you want to run other notebooks independently)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "c8afd1f9",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mPrecompiling RCall [6f49c342-dc21-5d91-9882-a32aef131414]\n",
      "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mNo R installation found by RCall.jl. Precompilation of RCall and all dependent packages postponed. Importing RCall will fail until an R installation is configured beforehand.\n",
      "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mSkipping precompilation since __precompile__(false). Importing RCall [6f49c342-dc21-5d91-9882-a32aef131414].\n",
      "\u001b[36m\u001b[1m[ \u001b[22m\u001b[39m\u001b[36m\u001b[1mInfo: \u001b[22m\u001b[39mNo R installation found by RCall.jl. Precompilation of RCall and all dependent packages postponed. Importing RCall will fail until an R installation is configured beforehand.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "You need to install 'DataFrames' and 'RCall' to compute the persistence of the labor process.\n",
      "This require an R installation.\n",
      "The persistence will not be computed (the rest of the computation is unaffected).\n"
     ]
    }
   ],
   "source": [
    "using Parameters                     # @unpack\n",
    "using QuantEcon:rouwenhorst,tauchen,simulate, stationary_distributions,MarkovChain  # Rouwenhorst + Tauchen\n",
    "using Roots:find_zero                # root finding\n",
    "using SparseArrays                   # sparse matrices\n",
    "using IterativeSolvers:powm!         # largest eigenvector + associated eigenvector\n",
    "using Plots                          # Plots\n",
    "using LinearAlgebra:I                # the identity matrix\n",
    "using NBInclude                      # including notebooks instead of jl files\n",
    "using MAT                            # Manipulating mat files for Matlab\n",
    "compute_persistence = true\n",
    "try \n",
    "    using DataFrames \n",
    "    using RCall\n",
    "catch\n",
    "    println(\"You need to install 'DataFrames' and 'RCall' to compute the persistence of the labor process.\")\n",
    "    println(\"This require an R installation.\")\n",
    "    println(\"The persistence will not be computed (the rest of the computation is unaffected).\")\n",
    "    compute_persistence = false;\n",
    "end;"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "334acb3d",
   "metadata": {},
   "source": [
    "## Including other notebooks  <a id=\"notebooks\"></a>[<font size=1>(back to menu)</font>](#menu)\n",
    "\n",
    "See above for a detailed description of each notebook.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "4d0e9cbe",
   "metadata": {},
   "outputs": [],
   "source": [
    "@nbinclude(\"Structures.ipynb\");  \n",
    "@nbinclude(\"SolveAiyagari.ipynb\");\n",
    "@nbinclude(\"Truncation.ipynb\");\n",
    "@nbinclude(\"Ramsey.ipynb\");\n",
    "@nbinclude(\"ToDynare.ipynb\");    \n",
    "@nbinclude(\"Utils.ipynb\");      \n",
    "@nbinclude(\"Reiter.ipynb\");\n",
    "if compute_persistence\n",
    "    @nbinclude(\"R_functions.ipynb\");\n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "28be01a5",
   "metadata": {},
   "source": [
    "## Computing the Ramsey solution <a id=\"comps\"></a>[<font size=1>(back to menu)</font>](#menu)\n",
    "\n",
    "All the steps are gathered in the same cell for the sake of convenience. These steps are the following ones.\n",
    "\n",
    "1. Definition of the variable `economy` of type `Economy` containing the setup parameters.\n",
    "\n",
    "2. Computation of the `solution` of the Aiyagari economy.\n",
    "\n",
    "3. Definition of the parameters for the truncation lengths: `N` (the uniform truncation length), `R` (the refined truncation length, identical for all idiosyncratic states), and `refiNs` (the vector of truncation lengths).\n",
    "\n",
    "4. Computation of the truncated model `truncatedModel`.\n",
    "\n",
    "5. Computation of the Ramsey solution `ramsey`.\n",
    "\n",
    "6. Saving the solution for Dynare in a `mat` file. We also save further data for the comparison with Reiter. \n",
    "\n",
    "The numbering in the cell is identical to the previous numbers.\n",
    "\n",
    "***Remark.*** We use several `check_` functions to verify the  internal consistency of the outputs. These functions by default do not print anything if no inconsistency is spotted. This can be changed by modifying the argument `noprint=true` to `noprint=false`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "f8905fc2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Solved in 1824 iterations\n",
      "01. Gini                               0.6199\n",
      "02. Debt-to-GDP, B/Y                   61.06%\n",
      "03. Public spending-to-GDP, G/Y        17.09%\n",
      "04. Aggregate consumption-to-GDP, C/Y  55.91%\n",
      "05. Capital-to-GDP, K/Y                270.0%\n",
      "06. Investment-to-GDP, I/Y             27.0%\n",
      "07. Transfers-to-GDP, Tt/Y             0.0%\n",
      "08. Aggregate labor supply, L          0.2335\n",
      "09. Average MPC                        0.0813\n",
      "10. Consumption tax-to-GDP             0.0%\n",
      "11. Labor tax-to-GDP                   15.15%\n",
      "12. Capital tax-to-GDP                 3.97%\n",
      "13. Total tax-to-GDP                   19.12%\n",
      "14. Share of credit-constrained agents 6.46%\n",
      "\n",
      "Number of credit-constrained truncated histories: 39 (out of 455)\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 1. Definition of the variable `economy`\n",
    "economy = Economy(\n",
    "    KsY    = 2.7*4,                # capital-to-output ratio (for setting discount factor β)\n",
    "    α      = 0.36,                 # capital share\n",
    "    δ      = 0.025,                # capital depreciation\n",
    "    σ      = 1.,                   # inverse of IES \n",
    "    χ      = 0.005168810358061675, # calibrated to match a proper value of K/L\n",
    "    φ      = 0.5,                  # Frisch elasticity\n",
    "    κ      = 0.75,                 # Level of the HSV non-linear labor tax\n",
    "    τ      = 0.82,                 # Curvature on the HSV non-linear labor tax\n",
    "    τk     = 0.36,                 # capital tax\n",
    "    Tt     = 0.,                   # lump-sum transfer (none in this model)\n",
    "    na     = 100,                  # nb of asset grid points\n",
    "    a_min  = 1e-9,                 # minimal asset holding\n",
    "    a_max  = 2000.0,               # maximal asset holding\n",
    "    curv_a = 4.0,                  # curvature of the exponential asset grid\n",
    "    n_ex_ante = 3,                 # nb of ex-ante types\n",
    "    yscales= [.8,1.0,2.0],         # scaling factors for ys per type\n",
    "    nys    = [5,5,5],              # nb of productivity states per ex ante type\n",
    "    ρys    = [0.986, 0.98, 0.98],  # quarterly persistence of productivity\n",
    "    σys    = [0.16, 0.131, 0.131], # quarterly SE of productivity innovation\n",
    "    ωys    = [1.,1.,1.],           # weights are automatically normalized \n",
    "    alg_y  = :rouwenhorst          # method of discretization for the productivity process  \n",
    "    );\n",
    "\n",
    "# 2. Computation of the `solution` of the Aiyagari economy.\n",
    "solution = steady(economy, print_step=20000, tolEGM=1e-12)\n",
    "check_solution(solution,economy,noprint=true)    # we check that there is no internal inconsistency.\n",
    "(print_dict∘describe_solution)(solution,economy) # we report some descriptive statistics of the solution \n",
    "\n",
    "# 3. Definition of the parameters for the truncation lengths\n",
    "N = 2    # Length of uniform truncation\n",
    "R = 10   # Length of the refinement\n",
    "refiNs = fill(N+R,maximum(economy.nys)) \n",
    "\n",
    "# 4. Computation of the truncated model `truncatedModel`.\n",
    "truncatedModel = TruncatedModel(N,refiNs,solution,economy,method=\"closest\")\n",
    "check_truncation(truncatedModel,solution,economy,noprint=true)  # we check that there is no internal inconsistency.\n",
    "println(\"\\nNumber of credit-constrained truncated histories: \",length(truncatedModel.truncatedAllocation.ind_cc_h),\n",
    "    \" (out of \",truncatedModel.Ntot,\")\\n\")\n",
    "\n",
    "# 5. Computation of the Ramsey solution `ramsey`.\n",
    "ramsey = Ramsey(truncatedModel,solution,economy)\n",
    "check_Ramsey(ramsey,solution,economy,noprint=true) # we check that there is no internal inconsistency.\n",
    "\n",
    "# 6. Saving the solution for Dynare.\n",
    "write_Dynare(\"toDynare.mat\",ramsey,solution,economy)\n",
    "write_Reiter(\"todynare_Reiter.mat\",solution,economy) # Located in the Reiter package\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c4e666b9-6686-4d7c-8e38-5696c786b47f",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "2f2cdd1ff8a9a8a92e81b30fa7793e569067293609a0a900778750ec785af5d3"
  },
  "kernelspec": {
   "display_name": "Julia 1.10.5",
   "language": "julia",
   "name": "julia-1.10"
  },
  "language_info": {
   "file_extension": ".jl",
   "mimetype": "application/julia",
   "name": "julia",
   "version": "1.10.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
